<template>
  <transition name="viewer-fade">
    <div
      class="el-image-viewer__wrapper z-wrap"
      :style="{ 'z-index': zIndex }"
    >
      <div class="el-image-viewer__mask" />
      <div class="image-viewer-zheader-wrap">
        <div class="left-wrap">
          <p class="img-info">
            {{ detailInfo.fileName || '未知' }}
          </p>
          <div class="record-info">
            <p>
              上传记录：{{ detailInfo.createUser || '系统' }}
              <span class="vertical-line">|</span>
              {{ curItem.uploadTime }}
              <span class="vertical-line">|</span>
              {{ detailInfo.channelName || '' }}
            </p>
            <p>
              图片状态：{{
                statusMap[detailInfo.checkStatus] || ''
              }}<span
                v-if="detailInfo.picFailedReason"
              >({{ detailInfo.picFailedReason || '' }})</span>
              <span class="vertical-line">|</span>
              {{ curItem.quoteFlag == 1 ? '已引用' : '未引用' }}
            </p>
            <p>
              尺寸大小：{{ detailInfo.width || '' }} x
              {{ detailInfo.height || '' }}
              <span class="vertical-line">|</span>
              {{ detailInfo.fileSize | coverUnit }}
            </p>
          </div>
        </div>
        <div class="right-wrap" @click="hide">
          <i class="icon-close" />
        </div>
      </div>
      <!-- ARROW -->
      <template v-if="!isSingle">
        <span
          class="el-image-viewer__btn el-image-viewer__prev"
          :class="{ 'is-disabled': !infinite && isFirst }"
          @click="prev"
        >
          <i class="el-icon-arrow-left" />
        </span>
        <span
          class="el-image-viewer__btn el-image-viewer__next"
          :class="{ 'is-disabled': !infinite && isLast }"
          @click="next"
        >
          <i class="el-icon-arrow-right" />
        </span>
      </template>
      <!-- ACTIONS -->
      <div v-if="fileList.length > 0" class="image-viewer-zfooter-wrap">
        <div class="left">
          <i
            class="icon-zoom-out"
            @click="handleActions('zoomOut')"
          />
          <i
            class="icon-zoom-in"
            @click="handleActions('zoomIn')"
          />
          <i
            class="icon-full-screen2"
            :class="{
              'icon-scale-to-original': mode.name === 'original'
            }"
            @click="toggleMode"
          />
          <i
            class="icon-refresh-left"
            @click="handleActions('anticlocelise')"
          />
          <i
            class="icon-refresh-right"
            @click="handleActions('clocelise')"
          />
        </div>
        <el-popover v-model="delVisible" placement="top" width="180">
          <p class="title-tip">
            {{
              curItem.quoteFlag == 1 || curItem.checkStatus == 1
                ? '已选图片无法删除'
                : '确定删除该图片吗？'
            }}
          </p>
          <p class="title-content">
            {{
              curItem.quoteFlag == 1 || curItem.checkStatus == 1
                ? curItem.quoteFlag == 1
                  ? '当前图片已被引用，未避免影响业务，无法进行删除。'
                  : '当前图片正在审核中，无法进行删除。'
                : '当前图片未被引用，删除后不影响当前业务。'
            }}
          </p>
          <div
            v-if="
              curItem.quoteFlag !== 1 && curItem.checkStatus !== 1
            "
            style="text-align: right; margin: 0"
          >
            <el-button
              size="mini"
              type="text"
              @click="delVisible = false"
            >取消</el-button>
            <el-button
              type="primary"
              size="mini"
              @click="handleDel"
            >确定</el-button>
          </div>
          <div slot="reference" class="center">
            删除
          </div>
        </el-popover>
        <el-popover
          placement="top-start"
          :title="`共${fileTag.length}个标签`"
          width="250"
          trigger="hover"
          :content="fileTag.join('、')"
        >
          <div
            v-show="fileTag.length > 0"
            slot="reference"
            class="right"
          >
            查看标签
          </div>
        </el-popover>
      </div>
      <!-- CANVAS -->
      <div class="el-image-viewer__canvas">
        <template v-for="(v, i) in fileList">
          <img
            v-if="i === index && v.checkStatus !== 3"
            ref="img"
            :key="v.fileId"
            class="el-image-viewer__img"
            :src="currentImg"
            :style="imgStyle"
            @load="handleImgLoad"
            @error="handleImgError"
            @mousedown="handleMouseDown"
            @mouseleave="handleMouseLeave"
          >
          <img
            v-if="i === index && v.checkStatus == 3"
            ref="img"
            :key="v.fileId"
            class="el-image-viewer__img"
            src="../../assets/images/commodity/img-no-data.png"
            :style="imgStyle"
            @load="handleImgLoad"
            @error="handleImgError"
            @mousedown="handleMouseDown"
            @mouseleave="handleMouseLeave"
          >
        </template>
      </div>
    </div>
  </transition>
</template>

<script>
import { on, off } from 'element-ui/src/utils/dom'
import { rafThrottle, isFirefox } from 'element-ui/src/utils/util'
import constants from '@/commons/constants'

const Mode = {
  CONTAIN: {
    name: 'contain',
    icon: 'el-icon-full-screen'
  },
  ORIGINAL: {
    name: 'original',
    icon: 'el-icon-c-scale-to-original'
  }
}

const mousewheelEventName = isFirefox() ? 'DOMMouseScroll' : 'mousewheel'

export default {
  name: 'ElImageViewer',
  filters: {
    coverUnit(limit = 0) {
      limit = Number(limit)
      let size = ''
      if (limit >= 1 * 1024 * 1024) {
        size = (limit / (1024 * 1024)).toFixed(2) + 'GB'
      } else if (limit >= 1 * 1024) {
        // 如果小于0.1GB转化成MB
        size = (limit / 1024).toFixed(2) + 'MB'
      } else if (limit >= 1) {
        size = limit.toFixed(2) + 'KB'
      } else {
        size = (limit * 1024).toFixed(2) + 'B'
      }
      const sizeStr = size + ''
      const len = sizeStr.indexOf('\.')
      const dec = sizeStr.substr(len + 1, 2)
      if (dec === '00') {
        // 当小数点后为00时 去掉小数部分
        return sizeStr.substring(0, len) + sizeStr.substr(len + 3, 2)
      }
      return sizeStr
    }
  },
  props: {
    fileList: {
      type: Array,
      default: () => []
    },
    zIndex: {
      type: Number,
      default: 2000
    },
    onSwitch: {
      type: Function,
      default: () => {}
    },
    onClose: {
      type: Function,
      default: () => {}
    },
    curIndex: {
      type: Number,
      default: 0
    },
    detailInfo: {
      type: Object,
      default: () => {}
    }
  },

  data() {
    return {
      index: 0,
      isShow: false,
      infinite: false,
      loading: false,
      mode: Mode.CONTAIN,
      transform: {
        scale: 1,
        deg: 0,
        offsetX: 0,
        offsetY: 0,
        enableTransition: false
      },
      statusMap: constants.PIC_CHECK_STATUS,
      delVisible: false
    }
  },
  computed: {
    fileTag() {
      const { fileTag } = this.detailInfo || {}
      return fileTag || []
    },
    curItem() {
      return this.fileList[this.index] || {}
    },
    isSingle() {
      return this.fileList && this.fileList.length <= 1
    },
    isFirst() {
      return this.index === 0
    },
    isLast() {
      return this.index === this.fileList.length - 1
    },
    currentImg() {
      const { relativeUrl } = this.fileList[this.index] || {}
      return relativeUrl || ''
    },
    imgStyle() {
      const {
        scale,
        deg,
        offsetX,
        offsetY,
        enableTransition
      } = this.transform
      const style = {
        transform: `scale(${scale}) rotate(${deg}deg)`,
        transition: enableTransition ? 'transform .3s' : '',
        'margin-left': `${offsetX}px`,
        'margin-top': `${offsetY}px`
      }
      if (this.mode === Mode.CONTAIN) {
        style.maxWidth = style.maxHeight = '100%'
      }
      // if (this.mode === Mode.ORIGINAL) {
      //     // style.width = style.height = '100%';
      //     style.width = '100%';
      // }
      return style
    }
  },
  watch: {
    curIndex: {
      handler(val) {
        this.index = val
      }
    },
    index: {
      handler(val) {
        this.reset()
        this.onSwitch(val)
      }
    },
    currentImg(val) {
      this.$nextTick(_ => {
        const $img = this.$refs && this.$refs.img && this.$refs.img[0]
        if ($img && !$img.complete) {
          this.loading = true
        }
      })
    }
  },
  mounted() {
    this.deviceSupportInstall()
    // this.$refs['el-image-viewer__wrapper'].focus();
  },
  beforeDestroy() {
    this.deviceSupportUninstall()
  },
  methods: {
    hide() {
      this.onClose()
    },
    deviceSupportInstall() {
      this._keyDownHandler = rafThrottle(e => {
        const keyCode = e.keyCode
        switch (keyCode) {
          // ESC
          case 27:
            this.hide()
            break
            // SPACE
          case 32:
            this.toggleMode()
            break
            // LEFT_ARROW
          case 37:
            this.prev()
            break
            // UP_ARROW
          case 38:
            this.handleActions('zoomIn')
            break
            // RIGHT_ARROW
          case 39:
            this.next()
            break
            // DOWN_ARROW
          case 40:
            this.handleActions('zoomOut')
            break
        }
      })
      this._mouseWheelHandler = rafThrottle(e => {
        const delta = e.wheelDelta ? e.wheelDelta : -e.detail
        if (delta > 0) {
          this.handleActions('zoomIn', {
            zoomRate: 0.015,
            enableTransition: false
          })
        } else {
          this.handleActions('zoomOut', {
            zoomRate: 0.015,
            enableTransition: false
          })
        }
      })
      on(document, 'keydown', this._keyDownHandler)
      on(document, mousewheelEventName, this._mouseWheelHandler)
    },
    deviceSupportUninstall() {
      off(document, 'keydown', this._keyDownHandler)
      off(document, mousewheelEventName, this._mouseWheelHandler)
      this._keyDownHandler = null
      this._mouseWheelHandler = null
    },
    handleImgLoad(e) {
      this.loading = false
    },
    handleImgError(e) {
      this.loading = false
      e.target.alt = '加载失败'
    },
    handleMouseDown(e) {
      if (this.loading || e.button !== 0) return

      const { offsetX, offsetY } = this.transform
      const startX = e.pageX
      const startY = e.pageY
      this._dragHandler = rafThrottle(ev => {
        this.transform.offsetX = offsetX + ev.pageX - startX
        this.transform.offsetY = offsetY + ev.pageY - startY
      })
      on(document, 'mousemove', this._dragHandler)
      on(document, 'mouseup', ev => {
        off(document, 'mousemove', this._dragHandler)
      })

      e.preventDefault()
    },
    handleMouseLeave() {
      off(document, 'mousemove', this._dragHandler)
    },
    reset() {
      this.transform = {
        scale: 1,
        deg: 0,
        offsetX: 0,
        offsetY: 0,
        enableTransition: false
      }
    },
    toggleMode() {
      if (this.loading) return
      const modeNames = Object.keys(Mode)
      const modeValues = Object.values(Mode)
      const index = modeValues.indexOf(this.mode)
      const nextIndex = (index + 1) % modeNames.length
      this.mode = Mode[modeNames[nextIndex]]
      this.reset()
    },
    prev() {
      if (this.isFirst && !this.infinite) {
        this.$message({
          message: '已经是当前页第一张',
          type: 'warning'
        })
        return
      }
      const len = this.fileList.length
      this.index = (this.index - 1 + len) % len
      const picId = this.fileList[this.index].fileId
      this.$emit('get-detail', picId)
    },
    next() {
      if (this.isLast && !this.infinite) {
        this.$message({
          message: '已经是当前页最后一张',
          type: 'warning'
        })
        return
      }
      const len = this.fileList.length
      this.index = (this.index + 1) % len
      const picId = this.fileList[this.index].fileId
      this.$emit('get-detail', picId)
    },
    handleDel() {
      const row = this.fileList[this.index]
      this.$emit('del-single', row, 'preview')
      this.delVisible = false
    },
    handleActions(action, options = {}) {
      if (this.loading) return
      const { zoomRate, rotateDeg, enableTransition } = {
        zoomRate: 0.2,
        rotateDeg: 90,
        enableTransition: true,
        ...options
      }
      const { transform } = this
      switch (action) {
        case 'zoomOut':
          if (transform.scale > 0.2) {
            transform.scale = parseFloat(
              (transform.scale - zoomRate).toFixed(3)
            )
          }
          break
        case 'zoomIn':
          transform.scale = parseFloat(
            (transform.scale + zoomRate).toFixed(3)
          )
          break
        case 'clocelise':
          transform.deg += rotateDeg
          break
        case 'anticlocelise':
          transform.deg -= rotateDeg
          break
      }
      transform.enableTransition = enableTransition
    }
  }
}
</script>

<style lang="scss">
.el-image-viewer__mask {
    opacity: 0.65;
}
.el-image-viewer__next,
.el-image-viewer__prev {
    background-color: #000;
}
</style>
<style lang="scss" scoped>
.image-viewer-zheader-wrap {
    width: 100%;
    height: 66px;
    background: #333;
    display: flex;
    align-items: center;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 3;
    .left-wrap {
        flex: 1;
        padding-left: 20px;
    }
    .right-wrap {
        width: 60px;
        text-align: center;
    }
    .img-info {
        font-size: 14px;
        font-family: PingFangSC-Medium;
        font-weight: 500;
        color: rgba(238, 238, 238, 1);
        line-height: 20px;
        text-align: left;
    }
    .record-info {
        display: flex;
        color: #eee;
        margin-top: 2px;

        p {
            margin-right: 30px;
            font-size: 12px;
        }
    }
    .vertical-line {
        color: #666;
        line-height: 17px;
        margin-left: 4px;
        margin-right: 4px;
    }
    .icon-close {
        display: inline-block;
        width: 20px;
        height: 20px;
        background: url('../assets/commodity/icon-close.png')
            no-repeat;
        background-size: 100% 100%;
    }
}
.image-viewer-zfooter-wrap {
    width: 100%;
    height: 66px;
    position: absolute;
    bottom: 0;
    left: 0;
    display: flex;
    justify-content: center;
    z-index: 1;
    .left {
        width: 262px;
        height: 44px;
        background: rgba(0, 0, 0, 0.59);
        border-radius: 22px;
        display: flex;
        justify-content: space-around;
        align-items: center;
        padding: 0 25px;
        box-sizing: border-box;
        i {
            width: 24px;
            height: 24px;
            display: inline-block;
        }
        .icon-zoom-out {
            background: url('../assets/commodity/icon-zoom-out.png')
                no-repeat;
            background-size: 100% 100%;
        }
        .icon-zoom-in {
            background: url('../assets/commodity/icon-zoom-in.png')
                no-repeat;
            background-size: 100% 100%;
        }
        .icon-full-screen2 {
            background: url('../assets/commodity/icon-full-screen.png')
                no-repeat;
            background-size: 100% 100%;
        }
        .icon-scale-to-original {
            background: url('../assets/commodity/icon-scale-to-original.png')
                no-repeat;
            background-size: 100% 100%;
        }
        .icon-refresh-left {
            background: url('../assets/commodity/icon-refresh-left.png')
                no-repeat;
            background-size: 100% 100%;
        }
        .icon-refresh-right {
            background: url('../assets/commodity/icon-refresh-right.png')
                no-repeat;
            background-size: 100% 100%;
        }
    }
    .center {
        width: 76px;
        height: 44px;
        background: rgba(0, 0, 0, 0.59);
        border-radius: 22px;
        text-align: center;
        line-height: 44px;
        color: #fff;
        margin-left: 30px;
    }
    .right {
        width: 102px;
        height: 44px;
        background: rgba(0, 0, 0, 0.59);
        border-radius: 22px;
        text-align: center;
        line-height: 44px;
        color: #fff;
        margin-left: 30px;
    }
}
</style>
